/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ru.ssau.berlin.jsf.beans;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import ru.ssau.berlin.ejb.facade.EventFacadeLocal;
import ru.ssau.berlin.ejb.facade.GroupFacadeLocal;
import ru.ssau.berlin.ejb.facade.PersonFacadeLocal;
import ru.ssau.berlin.ejb.facade.UniFacadeLocal;
import ru.ssau.berlin.entity.*;
import ru.ssau.berlin.jsf.util.FacesApplication;


/**
 *
 * @author Пользователь
 */
public class GroupView {

    @EJB
    private PersonFacadeLocal personFacade;
    @EJB
    private GroupFacadeLocal groupFacade;
    @EJB
    private EventFacadeLocal eventFacade;
    @EJB
    private UniFacadeLocal uniFacade;

    private static final String ID_PARAMETER = "id_param";

    private FacesApplication application = FacesApplication.getInstance();

    private String value;

    private PersonGroup group;
    private List<PersonGroup> groups;

    private GroupType type;
    private List<GroupType> types;
    private List<SelectItem> items;

    private GroupAttribute attr;
    private List<GroupAttribute> attrs;
    private List<SelectItem> attrItems;

    private List<AttributeType> attrTypes;
    private List<SelectItem> attrTypeItems;

    private List<SelectItem> personItems;
    private List<SelectItem> eventItems;
    private Person person;
    private Event event;

    private boolean readonly;

    /** Creates a new instance of GroupView */
    public GroupView() {
    }

    public List<PersonGroup> getGroups() {
        return groups;
    }

    public List<GroupType> getTypes() {
        return types;
    }

    public PersonGroup getGroup() {
        return group;
    }

    public void setGroup(PersonGroup group) {
        this.group = group;
    }

    public boolean isReadonly() {
        return readonly;
    }

    public void setReadonly(boolean readonly) {
        this.readonly = readonly;
    }

    public GroupType getType() {
        return type;
    }

    public void setType(GroupType type) {
        this.type = type;
    }

    public List<SelectItem> getItems() {
        return items;
    }

    public GroupAttribute getAttr() {
        return attr;
    }

    public void setAttr(GroupAttribute attr) {
        this.attr = attr;
    }

    public List<AttributeType> getAttrTypes() {
        return attrTypes;
    }

    public void setAttrTypes(List<AttributeType> attrTypes) {
        this.attrTypes = attrTypes;
    }

    public List<GroupAttribute> getAttrs() {
        return attrs;
    }

    public void setAttrs(List<GroupAttribute> attrs) {
        this.attrs = attrs;
    }

    public List<SelectItem> getAttrItems() {
        return attrItems;
    }

    public List<SelectItem> getAttrTypeItems() {
        return attrTypeItems;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public List<SelectItem> getEventItems() {
        return eventItems;
    }

    public List<SelectItem> getPersonItems() {
        return personItems;
    }

    public Event getEvent() {
        return event;
    }

    public void setEvent(Event event) {
        this.event = event;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public String showAllGroups() {
        groups = groupFacade.findAll();
        return application.getNavigator().goToGroupsList();
    }

    public String showGroup() {
        group = groupFacade.find(Long.parseLong(
                application.getRequestParameter(ID_PARAMETER)));
        types = new ArrayList<GroupType>(2);
        types.add(group.getType());
        generateGroupTypeSelectItems();
        generatePersonItems(getFreePersons(group));
        generateEventItems(getFreeEvents(group));
        readonly = true;
        return application.getNavigator().goToGroupView();
    }

    public String editGroup() {
        group = groupFacade.find(Long.parseLong(
                application.getRequestParameter(ID_PARAMETER)));
        attrs = new LinkedList<GroupAttribute>();
        for (GroupType currType = group.getType(); currType != null; currType = currType.getParent()) {
            attrs.addAll(currType.getAttributes());
        }
        for (GroupParameter param: group.getParameters()) {
            attrs.remove(param.getAttribute());
        }
        generateAttributeSelectItems();
        types = groupFacade.findGroupTypes();
        generateGroupTypeSelectItems();
        generatePersonItems(getFreePersons(group));
        generateEventItems(getFreeEvents(group));
        readonly = false;
        return application.getNavigator().goToGroupView();
    }

    public String newGroup() {
        group = new PersonGroup();
        types = groupFacade.findGroupTypes();
        generateGroupTypeSelectItems();
        readonly = false;
        return application.getNavigator().goToGroupView();
    }

    public String persistGroup() {
        if (group.getId() == null) {
            groupFacade.create(group);
        } else {
            groupFacade.edit(group);
        }
        return showAllGroups();
    }

    public String addParameter() {
        GroupParameter param = new GroupParameter();
        param.setAttribute(attr);
        param.setGroup(group);
        param.setParameterValue(value);
        groupFacade.createParameter(param);
        group = groupFacade.find(group.getId());
        attrs.remove(attr);
        generateAttributeSelectItems();
        return application.getNavigator().stayHere();
    }

    public void deleteParameter(ActionEvent event) {
        GroupParameter param = groupFacade.findParameter(Long.parseLong(
                event.getComponent().getAttributes().get(ID_PARAMETER).toString()));
        groupFacade.removeParameter(param);
        attrs.add(param.getAttribute());
        generateAttributeSelectItems();
        group = groupFacade.find(group.getId());
    }

    public void deleteGroup(ActionEvent event) {
        group = groupFacade.find(Long.parseLong(
                event.getComponent().getAttributes().get(ID_PARAMETER).toString()));
        groupFacade.remove(group);
    }

    public void joinPerson(ActionEvent event) {
        group.getPersons().add(person);
        person.getGroups().add(group);
        personFacade.edit(person);
        generatePersonItems(getFreePersons(group));
    }

    public String leavePerson() {
        person = personFacade.find(Long.parseLong(
                application.getRequestParameter(ID_PARAMETER)));
        group.getPersons().remove(person);
        person.getGroups().remove(group);
        personFacade.edit(person);
        generatePersonItems(getFreePersons(group));
        return application.getNavigator().stayHere();
    }

    public void joinEvent(ActionEvent e) {
        group.getEvents().add(event);
        generateEventItems(getFreeEvents(group));
        groupFacade.edit(group);
    }

    public String leaveEvent() {
        event = eventFacade.find(Long.parseLong(
                application.getRequestParameter(ID_PARAMETER)));
        group.getEvents().remove(event);
        groupFacade.edit(group);
        generateEventItems(getFreeEvents(group));
        return application.getNavigator().stayHere();
    }

    private void loadType() {
        type = groupFacade.findGroupType(Long.parseLong(
                application.getRequestParameter(ID_PARAMETER)));
    }

    private void generateGroupTypeSelectItems() {
        items = new ArrayList<SelectItem>(types.size());
        for (GroupType iter: types) {
            items.add(new SelectItem(iter, iter.toString()));
        }
    }

    private void generateAttributeSelectItems() {
        attrItems = new ArrayList<SelectItem>(attrs.size() + 1);
        for (GroupAttribute attribute: attrs) {
            attrItems.add(new SelectItem(attribute, attribute.getName()));
        }
    }

    private List<Person> getFreePersons(PersonGroup group) {
        List<Person> result = personFacade.findAll();
        result.removeAll(group.getPersons());
        return result;
    }

    private List<Event> getFreeEvents(PersonGroup group) {
        List<Event> result = eventFacade.findAll();
        result.removeAll(group.getEvents());
        return result;
    }

    private void generatePersonItems(List<Person> persons) {
        personItems = new ArrayList<SelectItem>(persons.size());
        for (Person iter: persons) {
            personItems.add(new SelectItem(iter, iter.getName()));
        }
    }

    private void generateEventItems(List<Event> events) {
        eventItems = new ArrayList<SelectItem>(events.size());
        for (Event iter: events) {
            eventItems.add(new SelectItem(iter, iter.getName()));
        }
    }

}
